﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace peonwar
{
    public class Unit : AnimatedSprite
    {
        // ---CONSTRUCTORS---
        public Unit()
        {
        }

        // ---PROPERTIES---
        // Ici tout simplement ce sont les propritétés qui ne sont pas sensé changer une fois attribuée a une instance
        public bool TeamBlue;
        public bool damaged;
        public int UnitType; // Type de l'uniter, int de 1 a 9
        public int Tick; // Pour les unitées tirant plusieurs balles par anims
        public int Range;
        public int Energy; // Cout en cooldown
        public int kill;

        // IDENTIFIANT DE L'UNITER
        public static int iterator;
        public int Identifier;

        protected double AnimationFactor = 0.25;

        // Randomization
        protected Random random;
        protected Random randomAttack;
        public int Seed;

        //Cout des unitées
        private int cost;
        public int Cost
        {
            get
            {
                return cost;
            }
            set
            {
                if (value >= 0)
                    cost = value;
                else
                    cost = 0;
            }
        }

        // Puissance d'attaque
        public double Power;

        // Vitesse de deplacement
        // Garder en memoire la speed de depart
        public double SpeedBase;
        public double Speed; // Pour eviter certains bugs, les modifications liés aux techs se font direct dans les sous-classes

        // Type de dommages infligés
        public DamageType AtkType;

        // Resistance aux differents types de dommages (en pourcentage, donc 100 = resistance totale, 0 = aucune resistance)
        public int projeResist;
        public int exploResist;
        public int sliceResist;

        // Resistance Generale, toujours en pourcentage (pourra permettre une amelioration de l'armure , pour plus tard )s
        public double OverallResistance;

        // Consistance actuelle, soit la vie... pour ceux qui comprenne pas "consistance"
        public double Health;
        // Consistance de départ
        public double MaxHealth;

        // Precision de tir
        public double Accuracy;

        // Etat du peon
        public UnitState State;

        // String precisant l'animation en cours
        public string CurrentAnim;

        // Depuis combien de temps le peon est mort ( Permet de solve les corps)
        public int DeadTime;

        // Hitbox pour les collisions
        private Rectangle ViewAttack;
        private Rectangle ViewFriend;
        // Distance du range allié
        protected int QueueOffset;

        private bool AttackingBase;

        // Texture du pion de minimap
        public Texture2D MinimapDot;
        public Color TeamColor;

        // couleur de l'unitée (pour les quakes)
        public Color drawingColor;

        //Pour reparer le bug du double kill
        private bool mustWaitForNextAttack;

        // Liste des agresseurs de l'unitée
        private List<Unit> Agressors;

        // ---METHODES---
        #region Methodes

        #region Initialize
        protected void Initialize(User player)
        {
            // Get son identifiant
            this.Identifier = Unit.iterator;
            Unit.iterator = Unit.iterator + 2;

            // Equipe, Spawn et Etat
            Agressors = new List<Unit>();
            drawingColor = Color.White;
            TeamBlue = player.TeamBlue;
            Position = player.SpawnPosition;
            State = UnitState.Walk;
            kill = 0;
            DeadTime = 0;
            AtkType = player.UnitAtkType[(UnitType - 1)];
            MaxHealth = player.UnitMaxHealth[UnitType - 1];
            Health = MaxHealth;
            AttackingBase = false;
            damaged = false;
            mustWaitForNextAttack = false;

            // Seed d'attaque
            this.random = new Random();
            this.Seed = random.Next(1, 101);
            this.randomAttack = new Random(this.Seed);

            // Pour adapter le cout a l'amelioration de la base 
            Cost = player.UnitCost[UnitType - 1];

            // Recupere les ameliorations du joueur localement
            double TechPower = player.TechPower[(UnitType - 1) / 3];
            double TechAccuracy = player.TechAccuracy[(UnitType - 1) / 3];
            double TechResist = player.TechResist[(UnitType - 1) / 3];
            double TechSpeed = player.TechSpeed[(UnitType - 1) / 3];

            // Attribution des stats
            Power = player.UnitPower[UnitType - 1];
            Accuracy = player.UnitAccuracy[UnitType - 1] / TechAccuracy;
            OverallResistance += player.UnitResist[(UnitType - 1) / 3];
            Range = player.UnitRange[UnitType - 1];
            Tick = player.UnitTick[UnitType - 1];
            exploResist = player.UnitexploResist[UnitType - 1];
            projeResist = player.UnitprojeResist[UnitType - 1];
            sliceResist = player.UnitsliceResist[UnitType - 1];
            Speed = player.UnitSpeed[UnitType - 1];
            SpeedBase = Speed;

            // Met l'animation a marcher
            Play = true;
            AnimationWalk();
            Animationspeed = AnimationFactor * Speed;

            // Miroir des sprites en fonction de l'equipe
            if (TeamBlue)
                this.Effect = SpriteEffects.FlipHorizontally;
            else
                this.Effect = SpriteEffects.None;

            // Initialisation de la hitbox d'attaque
            if (TeamBlue)
            {
                this.ViewAttack = new Rectangle((int)Position.X, (int)Position.Y - 30, this.Range, 60);
                this.ViewFriend = new Rectangle((int)Position.X, (int)Position.Y - 10, this.QueueOffset, 20);
            }
            else
            {
                this.ViewAttack = new Rectangle((int)Position.X - this.Range, (int)Position.Y - 30, this.Range, 60);
                this.ViewFriend = new Rectangle((int)Position.X - this.QueueOffset, (int)Position.Y - 10, this.QueueOffset, 20);
            }

            // Initialisation de la couleur d'equipe (pour la minimap)
            if (TeamBlue)
                this.TeamColor = Color.SkyBlue;
            else
                this.TeamColor = Color.Red;
            MinimapDot = GameTexture.TextureMinimap[(UnitType - 1) / 3];
        }

        public void InitializeAfterDeserialization(UnitInfos infos)
        {
            this.UnitType = infos.UnitType;
            this.Power = infos.Power;
            this.Accuracy = infos.Accuracy;
            this.OverallResistance = infos.OverallResistance;
            this.exploResist = infos.exploResist;
            this.projeResist = infos.projeResist;
            this.sliceResist = infos.sliceResist;
            this.Speed = infos.Speed;
            this.MaxHealth = infos.MaxHealth;
            this.Cost = infos.Cost;
            this.drawingColor = infos.drawingColor;

            this.Seed = infos.Seed;
            this.randomAttack = new Random(this.Seed);

            this.Identifier = infos.Identifier;

            this.Health = this.MaxHealth;

            this.SpeedBase = this.Speed;
            Animationspeed = AnimationFactor * Speed;
        }

        #endregion

        public void SetBaseSpeed()
        {
            this.Speed = this.SpeedBase;
            Animationspeed = AnimationFactor * Speed;
        }

        #region UpDate
        public void UpDate(GameTime gameTime, User player, User enemy, int index, int ticks)
        {
            // Test de mort
            if (this.Health <= 0)
                this.Die(player, enemy, index, ticks);

            // --- DEPLACEMENT ---
            // test de collision avant tout
            if (this.DeadTime == 0)
                ViewTest(player, enemy, ticks);

            // Le peon avance en fonction de son Etat, de sa vitesse et de son equipe
            // et cela tant qu'aucun allié ne gène le passage

            //Le Peon a t'il recus des degats
            if (!damaged /*Autant ne pas refaire le test si on connais la reponse*/ && Health != MaxHealth)
                damaged = true;

            // La variable prend -1 ou 1 en fonction de la team (red ou blue)
            int sign = -1;
            if (TeamBlue)
                sign = 1;

            // Retourne vrai si il y a collision alliee
            bool FriendCollision = false;
            int indexvivant = index - 1;
            if (index != 0)
            {
                for (int i = indexvivant; i >= 0; i--)
                {
                    if (player.PeonList[i].DeadTime == 0)
                    {
                        indexvivant = i;
                        break;
                    }
                }
               

                FriendCollision = ViewFriend.Contains((int)player.PeonList[indexvivant].Position.X, (int)player.PeonList[indexvivant].Position.Y)
                                   && player.PeonList[indexvivant].CurrentAnim != "DIE";
            }
            if (State == UnitState.Walk)
            {
                // Si cest le premier de la liste OU qu'il ny a pas collision alliee
                if (index == 0 || !FriendCollision)
                {
                    // Le peon avance
                    Position = new Vector2(Position.X + (float)Speed * sign, Position.Y);
                    // Deplacement des hitboxs
                    if (TeamBlue)
                    {
                        this.ViewAttack = new Rectangle((int)Position.X, (int)Position.Y - 30, this.Range, 60);
                        this.ViewFriend = new Rectangle((int)Position.X, (int)Position.Y - 10, this.QueueOffset, 20);
                    }
                    else
                    {
                        this.ViewAttack = new Rectangle((int)Position.X - this.Range, (int)Position.Y - 30, this.Range, 60);
                        this.ViewFriend = new Rectangle((int)Position.X - this.QueueOffset, (int)Position.Y - 10, this.QueueOffset, 20);
                    }
                }
                if (FriendCollision)
                {
                    if (this.Speed > player.PeonList[indexvivant].Speed)
                    { // Adapte la vitesse
                        this.Speed = player.PeonList[indexvivant].Speed;
                        this.Animationspeed = this.AnimationFactor * this.Speed;
                    }
                    else
                    { // Ou s'arrete
                        // Le peon s'arrete
                        State = UnitState.Stop;
                        AnimationIdle();
                        // Pour désynchroniser les animation des péons
                        Index = random.Next(0, Indexmax);
                    }
                }
            }

            if (State == UnitState.Stop && !FriendCollision)
            {
                if (index == 0 || this.SpeedBase <= player.PeonList[indexvivant].Speed)
                    SetBaseSpeed();
                State = UnitState.Walk;
                AnimationWalk();
                Index = random.Next(0, Indexmax);
            }

            // --- ANIMATION ---
            // Seul l'animation "marcher", drawin et drawout depend de la vitesse du peon
            if (Play)
            {
                if (CurrentAnim == "WALK")
                    Index += Animationspeed;
                else
                    if (CurrentAnim == "DRAWIN" || CurrentAnim == "DRAWOUT")
                        Index += AnimationFactor * SpeedBase;
                    else
                        if (CurrentAnim != "DIE" || (CurrentAnim == "DIE" && Index + 0.15 < Indexmax + 1))
                        {
                            Index += 0.15;
                        }
            }

            // Lorsque l'animation est terminer
            if (Index >= Indexmax + 1)
            {
                // Si l'animation est looper (marcher, tirer ou idle) on reset l'index
                if (CurrentAnim == "WALK" || CurrentAnim == "FIRE" || CurrentAnim == "IDLE")
                    Index = 0;
                else
                // Sinon on on enchaine avec une autre animation en fonction de la premiere
                {
                    switch (CurrentAnim)
                    {
                        case ("DRAWIN"):
                            AnimationFire();
                            if (AttackingBase)
                                this.State = UnitState.FireBase;
                            else
                                this.State = UnitState.Fire; break;
                        case ("DRAWOUT"):
                            AnimationWalk();
                            if (index == 0 || this.SpeedBase <= player.PeonList[index - 1].Speed)
                                SetBaseSpeed();
                            this.State = UnitState.Walk; break;
                    }
                }
            }
        }
        #endregion

        #region Animations
        // Methode pour lancer les animations
        public virtual void AnimationIdle()
        {
            Index = 0;
            CurrentAnim = "IDLE";
        }
        public virtual void AnimationWalk()
        {
            Index = 0;
            CurrentAnim = "WALK";
        }
        public virtual void AnimationDrawIn()
        {
            Index = 0;
            CurrentAnim = "DRAWIN";
        }
        public virtual void AnimationFire()
        {
            Index = 0;
            CurrentAnim = "FIRE";
        }
        public virtual void AnimationDrawOut()
        {
            Index = 0;
            CurrentAnim = "DRAWOUT";
        }
        public virtual void AnimationDie()
        {
            Index = 0;
            CurrentAnim = "DIE";
        }
        #endregion

        #region Draw
        public override void Draw(SpriteBatch spriteBatch, Camera camera)
        {
            // test des hitboxs
            // spriteBatch.Draw(GameTexture.UnitHealth, ViewAttack, Color.White);
            // spriteBatch.Draw(GameTexture.UnitHealthBar, ViewFriend, Color.White);

            // Peon

            // Redefinition de "Position" par rapport a la camera
            int c = 0;
            if (camera != null)
                c = camera.Position;
            Vector2 Position = new Vector2(this.Position.X - c, this.Position.Y);

            int newoffset = Offset;
            if (!TeamBlue)
                newoffset = -newoffset;
            int newindex = (int)Math.Floor(Index);
            Rectangle Desti = new Rectangle((int)Position.X - (Imgwidth / 2) + newoffset, (int)Position.Y - Imgheight, Imgwidth, Imgheight);
            Rectangle Source = new Rectangle((newindex * Imgwidth), 0, Imgwidth, Imgheight);
            spriteBatch.Draw(Texture, Desti, Source, new Color(drawingColor.R - (255 - Fade), drawingColor.G - (255 - Fade), drawingColor.B - (255 - Fade), Fade), 0f, Vector2.Zero, Effect, 0f);
            // tests origine
            // spriteBatch.Draw(GameTexture.UnitHealth, new Rectangle((int)Position.X - 1, (int)Position.Y - 1, 3, 3), Color.White);
            //spriteBatch.DrawString(GameData.Font_Simple, "" + this.Seed, Position, Color.Red);
            //spriteBatch.DrawString(GameData.Font_Simple, "" + this.Identifier, new Vector2(Position.X, Position.Y + 20), Color.Blue);
            //for (int i = 0; i < Agressors.Count; i++)
            //   spriteBatch.DrawString(GameData.Font_Simple, "" + Agressors[i].Identifier, new Vector2(Position.X, Position.Y - 60 - (i * 20)), Color.Blue);

            // Barre de vie
            if (Health < MaxHealth && this.CurrentAnim != "DIE")
            {
                int bar = (int)Math.Ceiling(20 * Health / MaxHealth);
                spriteBatch.Draw(GameTexture.UnitHealthBar, new Rectangle((int)Position.X - 11, (int)Position.Y - 55, 22, 5), Color.White);
                spriteBatch.Draw(GameTexture.UnitHealth, new Rectangle((int)Position.X - 10, (int)Position.Y - 54, bar, 3), Color.White);
            }

            // Minimap
            if (DeadTime == 0 && Position.X + c > 65 && Position.X + c < Game.CurrentMap.Length - 65)
            {
                int x = ((((int)Position.X + c) * 317) / Game.CurrentMap.Length) + 962;
                spriteBatch.Draw(MinimapDot, new Rectangle(x - 4, 660, 8, 13), TeamColor);
            }
        }
        #endregion

        #region Die/Fire/Attack/AttackBase
        public virtual void Die(User player, User playerenemy, int hisIndex, int ticks)
        {
            // On effectue des actions seulement si l'unitée n'est pas deja morte
            this.Speed = 0;// C'est ici pour reparer un bug incomprehensible...
            if (this.CurrentAnim != "DIE")
            {
                this.AnimationDie();
                // On joue le son de mort
                switch (this.UnitType)
                {
                    case (1):
                        this.PlaySound(1, 0.5f); break;
                    case (2):
                        this.PlaySound(1, 0.5f); break;
                    case (3):
                        this.PlaySound(1, 0.5f); break;
                    case (4):
                        this.PlaySound(1, 0.5f); break;
                    case (5):
                        this.PlaySound(1, 0.3f); break;
                    case (6):
                        this.PlaySound(1, 0.3f); break;
                    case (7):
                        this.PlaySound(1, 0.3f); break;
                    case (8):
                        this.PlaySound(1, 0.2f); break;
                    case (9):
                        this.PlaySound(1, 0.2f); break;
                    default:
                        this.PlaySound(1, 0.5f); break;
                }
                // On donne du fric au joueur attaquant
                int gain = (int)(this.Cost / 2);
                Tools.BankManage(playerenemy, gain);
                if (player.productBonus)
                {
                    gain = (int)((this.Cost * 0.10));
                    Tools.BankManage(player, gain);
                }
                // ICI c'est pour permettre aux unitées derrieres le mort de reprendre leurs vitesses
                if (player.PeonList.Count > hisIndex + 1 && player.PeonList[hisIndex + 1].Speed != player.PeonList[hisIndex + 1].SpeedBase)
                {
                    player.PeonList[hisIndex + 1].Speed = player.PeonList[hisIndex + 1].SpeedBase;
                    player.PeonList[hisIndex + 1].Animationspeed = player.PeonList[hisIndex + 1].AnimationFactor * player.PeonList[hisIndex + 1].Speed;
                }
                foreach (Unit unit in this.Agressors)
                    if (unit.DeadTime == 0)
                        if (!unit.EnemyCollision(playerenemy, player, ticks, hisIndex + 1))
                        {
                            unit.AnimationDrawOut();
                            unit.State = UnitState.DrawOut;
                            unit.mustWaitForNextAttack = false;
                        }
            }
        }

        protected virtual void Fire(bool firebase, User enemy)
        {
        }

        // Cette fonction n'est pas commenté! (Actuellement pour cause de fleme)
        // Si vraiment vous voulez tacher de la comprendre... A vos risques et periles
        public void Attack(User player, User playerenemy, int enemyindex, int ticks)
        {
            Unit enemy = playerenemy.PeonList[enemyindex];
            bool jihad = false;
            if (enemy.UnitType == 7 && this.UnitType == 6 && enemy.Health == enemy.MaxHealth)
                jihad = true;
            if (!enemy.Agressors.Contains(this))
                enemy.Agressors.Add(this);

            if (this.CurrentAnim != "DIE")
            {
                if ((this.State == UnitState.Walk || this.State == UnitState.Stop) && enemy.DeadTime == 0 && this.DeadTime == 0)
                {
                    this.State = UnitState.DrawIn;
                    this.AnimationDrawIn();
                    mustWaitForNextAttack = false;
                }
                if (this.State == UnitState.Fire && (this.Index == 0 || ticks == this.Tick))
                {
                    this.Fire(false, playerenemy);
                    if (!mustWaitForNextAttack)
                    {
                        switch (this.UnitType)
                        {
                            case (1):
                                this.PlaySound(2, 0.5f); break;
                            case (2):
                                this.PlaySound(2, 0.2f); break;
                            case (3):
                                this.PlaySound(2, 0.5f); break;
                            case (4):
                                this.PlaySound(2, 0.25f); break;
                            case (5):
                                this.PlaySound(2, 0.15f); break;
                            case (6):
                                this.PlaySound(2, 0.3f); break;
                            case (7):
                                this.PlaySound(2, 0.5f); break;
                            case (8):
                                this.PlaySound(2, 0.5f); break;
                            case (9):
                                this.PlaySound(2, 0.2f); break;
                            default:
                                this.PlaySound(2, 0.5f); break;
                        }
                        int resistance = (int)enemy.OverallResistance;
                        switch (this.AtkType)
                        {
                            case DamageType.Projectile:
                                resistance += enemy.projeResist;
                                break;
                            case DamageType.Explosif:
                                resistance += enemy.exploResist;
                                break;
                            case DamageType.Sliced:
                                resistance += enemy.sliceResist;
                                break;
                        }
                        if (resistance >= 100)
                            resistance = 99;
                        int puissanceDeFeu = (int)(this.Power - randomAttack.Next(0, (int)this.Accuracy));
                        double degat = (puissanceDeFeu - puissanceDeFeu * resistance / 100);
                        enemy.Health -= degat;
                        if (player.Type == PlayerType.Player)
                            AchievementManager.AchievementList[13].Add((int)degat);
                        //XP
                        float bonus = (player.character == Perso.Kruiser ? 1.3f : 1 );
                        player.Experience += (int)((degat * 2.5 * bonus) / ((double)player.Level * 0.5 + 1));
                        if (!playerenemy.IsBleeding && SettingManager.CurrentProfil.Blood)
                        {
                            if (enemy.UnitType < 7 && ((random.Next(0, 3) == 0) || this.Tick == -1))
                            {
                                playerenemy.IsBleeding = true;
                            }
                        }
                    }
                    mustWaitForNextAttack = false;
                }
                if (enemy.Health <= 0 && enemy.DeadTime < 5)
                {
                    if (jihad && player.Type == PlayerType.Player)
                        AchievementManager.AchievementList[20].Add();
                    mustWaitForNextAttack = true;
                    if (enemy.CurrentAnim != "DIE")
                    {
                        if (player.Type == PlayerType.Player && this.UnitType == 1 && enemy.UnitType == 7)
                            AchievementManager.AchievementList[21].Add();
                        if (enemy.AttackingBase)
                            player.Attacked = false;
                        this.kill++;
                        if (player.Type == PlayerType.Player)
                        {
                            AchievementManager.AchievementList[1].Add();
                            if (this.kill == 8 && UnitType == 10)
                                AchievementManager.AchievementList[9].Add();
                            if (enemy.UnitType == 8 && this.AtkType == DamageType.Projectile)
                                AchievementManager.AchievementList[12].Add();
                        }
                        float vol = (float)SettingManager.CurrentProfil.QuakeVol / 10f;
                        if (UnitType != 10)
                        {
                            switch (this.kill)
                            {
                                case 4:
                                    if (SettingManager.CurrentProfil.Quake != -1)
                                        GameSound.QuakeSounds[0 + SettingManager.CurrentProfil.Quake].Play(vol, 0, 0);
                                    this.drawingColor = Color.Yellow;
                                    this.Accuracy = this.Accuracy / 2;
                                    if (player.character == Perso.Emelle)
                                        this.Health += (MaxHealth - Health) / 2;
                                    player.Experience += 20;
                                    User.AdvertList.Add(new Advert(new Vector2(Position.X - 100, Position.Y - 80), GameData.Font_Quake, "Dominating", 1.5f, new Vector2(0, -1), 1f, this.drawingColor, true, false));
                                    break;
                                case 7:
                                    if (SettingManager.CurrentProfil.Quake != -1)
                                        GameSound.QuakeSounds[1 + SettingManager.CurrentProfil.Quake].Play(vol, 0, 0);
                                    this.drawingColor = Color.LightSkyBlue;
                                    this.OverallResistance += 5;
                                    if (player.character == Perso.Emelle)
                                        this.Health += (MaxHealth - Health) / 2;
                                    player.Experience += 30;
                                    User.AdvertList.Add(new Advert(new Vector2(Position.X - 100, Position.Y - 80), GameData.Font_Quake, "Rampage", 1.5f, new Vector2(0, -1), 1f, this.drawingColor, true, false));

                                    break;
                                case 10:
                                    if (SettingManager.CurrentProfil.Quake != -1)
                                        GameSound.QuakeSounds[2 + SettingManager.CurrentProfil.Quake].Play(vol, 0, 0);
                                    this.drawingColor = Color.Cyan;
                                    this.Power *= 1.5;
                                    if (player.character == Perso.Emelle)
                                        this.Health += (MaxHealth - Health) / 2;
                                    player.Experience += 40;
                                    User.AdvertList.Add(new Advert(new Vector2(Position.X - 100, Position.Y - 80), GameData.Font_Quake, "Monster Kill", 1.5f, new Vector2(0, -1), 1f, this.drawingColor, true, false));
                                    break;
                                case 13:
                                    if (SettingManager.CurrentProfil.Quake != -1)
                                        GameSound.QuakeSounds[3 + SettingManager.CurrentProfil.Quake].Play(vol, 0, 0);
                                    this.drawingColor = Color.Magenta;
                                    this.OverallResistance += 10;
                                    if (player.character == Perso.Emelle)
                                        this.Health = MaxHealth;
                                    player.Experience += 60;
                                    User.AdvertList.Add(new Advert(new Vector2(Position.X - 100, Position.Y - 80), GameData.Font_Quake, "GodLike", 1.5f, new Vector2(0, -1), 1f, this.drawingColor, true, false));
                                    break;
                                case 16:
                                    if (SettingManager.CurrentProfil.Quake != -1)
                                        GameSound.QuakeSounds[4 + SettingManager.CurrentProfil.Quake].Play(vol, 0, 0);
                                    this.drawingColor = Color.Red;
                                    this.Power *= 1.5;
                                    this.OverallResistance += 10;
                                    this.Accuracy = this.Accuracy / 2;
                                    if (player.character == Perso.Emelle)
                                        this.Health += (MaxHealth - Health) / 2;
                                    player.Experience += 80;
                                    if (player.Type == PlayerType.Player)
                                        AchievementManager.AchievementList[8].Add();
                                    User.AdvertList.Add(new Advert(new Vector2(Position.X - 100, Position.Y - 80), GameData.Font_Quake, "Holy Shit", 1.5f, new Vector2(0, -1), 1f, this.drawingColor, true, false));
                                    break;
                            }
                        }
                    }
                }
                if (mustWaitForNextAttack)
                    mustWaitForNextAttack = false;
                if (Game.firstblood && enemy.CurrentAnim == "DIE")
                {
                    if (SettingManager.CurrentProfil.Quake != -1)
                        GameSound.QuakeSounds[5 + SettingManager.CurrentProfil.Quake].Play((float)SettingManager.CurrentProfil.QuakeVol / 10f, 0, 0);
                    Game.firstblood = false;
                    player.Experience += 60;
                    if ( player.Type == PlayerType.Player)
                    AchievementManager.AchievementList[17].Add();
                    User.AdvertList.Add(new Advert(new Vector2(600, 280), GameData.Font_Profil, "FIRST BLOOD !", 1.5f, new Vector2(0, -1), 1f, Color.DarkRed, false, new Vector2(1f, 3.5f), true));
                }
            }
        }

        public void AttackBase(User player, User playerenemy, int ticks)
        {
            if (this.CurrentAnim != "DIE")
            {
                if (this.State == UnitState.Walk && this.DeadTime == 0)
                {
                    this.State = UnitState.DrawIn;
                    this.AttackingBase = true;
                    this.AnimationDrawIn();
                    playerenemy.Attacked = true;
                }
                if (this.State == UnitState.FireBase && (this.Index == 0 || ticks == this.Tick))
                {
                    this.Fire(true, playerenemy);
                    PlaySound(2, 0.2F);
                    int denom;
                    if (playerenemy.baseBonus && this.AtkType != DamageType.Explosif)
                        denom = 4;
                    else
                        denom = 1;
                    int degat = (int)((this.Power - randomAttack.Next(0, (int)this.Accuracy) / 2) / denom);
                    player.Experience += (int)(((double)degat * 2) / ((double)player.Level * 0.5 + 1));
                    playerenemy.BaseHealth -= degat;
                    if (playerenemy.BaseHealth < playerenemy.MaxBaseHealth / 10 && !playerenemy.finishhim)
                    {
                        playerenemy.finishhim = true;
                        GameSound.QuakeSounds[11 + SettingManager.CurrentProfil.Quake].Play();
                        User.AdvertList.Add(new Advert(new Vector2(600, 280), GameData.Font_Profil, "FINISH HIM !", 1.5f, new Vector2(0, -1), 1f, Color.Yellow, false, new Vector2(1f, 3.5f), true));

                    }
                }
            }
            else playerenemy.Attacked = false;
        }
        #endregion

        // Joue un son en fonction du type de l'unité et de l'int x :
        // 0 pop
        // 1 meurs
        // 2 tir
        public virtual void PlaySound(int x, float vol)
        {
            float f = 0;
            if (SettingManager.CurrentProfil.Pan)
            {
                float midwidth = (Game.camera.ViewWidth / 2);
                f = this.Position.X - (Game.camera.Position + midwidth);
                f = Tools.Born(-midwidth, midwidth, f);
                f = f / midwidth;
            }
            GameSound.UnitSound[UnitType - 1, x].Play(vol, 0, f);
        }

        // Test de collision d'attaque ennemie + base
        // player : user allié, playerenemy : user ennemie
        // index : rang de l'unité dans la liste
        private void ViewTest(User player, User playerenemy, int ticks)
        {
            int sign = -1;
            if (TeamBlue)
                sign = 1;
            // Test base adverse
            if (sign * (this.Position.X + (this.Range * sign)) >= sign * (playerenemy.SpawnPosition.X + (150 * -sign)))
            {
                this.AttackBase(player, playerenemy, ticks);
                return;
            }
            else
                  EnemyCollision(player, playerenemy, ticks, 0);

               
        }

        private bool EnemyCollision(User player, User playerenemy, int ticks, int index)
        {
            if (playerenemy.PeonList.Count > index)
            {
                if (playerenemy.PeonList[index].DeadTime < 15)
                {
                    if (this.ViewAttack.Contains((int)playerenemy.PeonList[index].Position.X, (int)playerenemy.PeonList[index].Position.Y))
                    {
                        this.Attack(player, playerenemy, index, ticks);
                        return true;
                    }
                }
                else
                    EnemyCollision(player, playerenemy, ticks, index + 1);
            }
            return false;
        }
        #endregion


        // Obtient le UnitTransfert contenant les infos de l'uniter
        public UnitTransfert GetModel()
        {
            UnitTransfert model = new UnitTransfert();
            model.agressors = new List<int>();

            for (int i = 0; i < Agressors.Count; i++)
                model.agressors.Add(Agressors[i].Identifier);

            model.Identifier = this.Identifier;

            model.damaged = this.damaged;
            model.kill = this.kill;
            model.AnimationFactor = this.AnimationFactor;
            model.Speed = this.Speed;
            model.Health = this.Health;
            model.State = this.State;
            model.CurrentAnim = this.CurrentAnim;
            model.DeadTime = this.DeadTime;
            model.ViewAttack = this.ViewAttack;
            model.ViewFriend = this.ViewFriend;
            model.AttackingBase = this.AttackingBase;
            model.drawingColor = this.drawingColor;
            model.mustWaitForNextAttack = this.mustWaitForNextAttack;

            // Animated sprite
            model.Play = this.Play;
            model.Animationspeed = this.Animationspeed;
            model.Offset = this.Offset;
            model.Index = this.Index;
            model.Indexmax = this.Indexmax;

            // Sprite
            model.Fade = this.Fade;
            model.Position = this.Position;

            return model;
        }

        // Met a jour les champs de l'uniter avec le UnitTransfert passe en parametre
        public void ActualizeUnit(UnitTransfert model, List<Unit> enemyList)
        {
            switch (model.CurrentAnim)
            {
                case "IDLE": AnimationIdle(); break;
                case "WALK": AnimationWalk(); break;
                case "DRAWIN": AnimationDrawIn(); break;
                case "DRAWOUT": AnimationDrawOut(); break;
                case "FIRE": AnimationFire(); break;
                case "DIE": AnimationDie(); break;
            }
            
            this.Agressors = new List<Unit>();
            for (int i = 0; i < model.agressors.Count; i++)
            {
                for (int j = 0; j < Math.Min(5, enemyList.Count); j++)
                {
                    if (model.agressors[i] == enemyList[j].Identifier)
                    {
                        this.Agressors.Add(enemyList[j]);
                        break;
                    }
                }
            }

            this.damaged = model.damaged;
            this.kill = model.kill;
            this.AnimationFactor = model.AnimationFactor;
            this.Speed = model.Speed;
            this.Health = model.Health;
            this.State = model.State;
            this.CurrentAnim = model.CurrentAnim;
            this.DeadTime = model.DeadTime;
            this.ViewAttack = model.ViewAttack;
            this.ViewFriend = model.ViewFriend;
            this.AttackingBase = model.AttackingBase;
            this.drawingColor = model.drawingColor;
            this.mustWaitForNextAttack = model.mustWaitForNextAttack;

            // Animated sprite
            this.Play = model.Play;
            this.Animationspeed = model.Animationspeed;
            this.Offset = model.Offset;
            this.Index = model.Index;
            this.Indexmax = model.Indexmax;

            // Sprite
            this.Fade = model.Fade;
            this.Position = model.Position;
        }
    }
}
